package com.gofun.framework.core.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

/**
 * @Project       : framework-core
 * @Program Name  : com.ljt.framework.core.utils.DictUtils.java
 * @Description   : 数据字典工具类
 * @Author        : chichangchao
 * @Creation Date : 2016年5月19日 下午5:09:58 
 * @ModificationHistory  
 * Who          When             What 
 * ----------   -------------    -----------------------------------
 * chichangchao     2016年5月19日        create
 */
public final class DictUtils {
  
  /**
   * CD_TAG:字典字段代码标识
   */
  public static final String CD_TAG = "Cd";
  
  /**
   * DSCP_TAG:字典字段描述标识
   */
  public static final String DSCP_TAG = "Dscp";
  
  /**
   * CD_DSCP_TAG:字典字段代码描述标识
   */
  public static final String CD_DSCP_TAG = "CdDscp";
  
  /**
   * 禁用实例化
   */
  private DictUtils(){}
  
  /** 
   *  @Description	: 获取某个对象的全部字典类型
   *  @return         : List<String>
   *  @Creation Date  : 2016年5月23日 上午1:01:59 
   *  @Author         : chichangchao
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public static List<String> getTyps(Object obj) {
    if(obj == null) return null;
    List<String> typs = new ArrayList<>();
    if(obj instanceof Map){
      Set<Entry<String, Object>> set = ((Map) obj).entrySet();
      for (Entry<String, Object> entry : set) {
        String key = entry.getKey();
        if(key.endsWith(CD_TAG))
          typs.add(StringUtils.removeEndStr(key, CD_TAG));
      }
    }else{
      Field[] fields = ReflectUtils.getFields(obj);
      for (Field field : fields) {
        String fieldName = field.getName();
        if(fieldName.endsWith(CD_TAG))
          typs.add(StringUtils.removeEndStr(fieldName, CD_TAG));
      }
    }
    return typs;
  }
  
  /** 
   *  @Description	: 根据字典更新某个对象的描述内容
   *  @return         : void
   *  @Creation Date  : 2016年5月23日 上午1:02:15 
   *  @Author         : chichangchao
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public static void updateDscp(Map<String, List<?>> dictCache, Object obj) 
      throws IllegalArgumentException, IllegalAccessException {
    if(obj == null) return;
    if(obj instanceof Map){
      Set<Entry<String, Object>> set = ((Map) obj).entrySet();
      String key = null;
      String typ = null;
      for (Entry<String, Object> entry : set) {
        key = entry.getKey();
        if(key.endsWith(CD_TAG)){
          typ = StringUtils.removeEndStr(key, CD_TAG);
          setDscp(obj, typ, getDscp(dictCache, typ, entry.getValue().toString()));
        }
      }
    }else{
      Field[] fields = ReflectUtils.getFields(obj);
      String fieldName = null;
      String typ = null;
      for (Field field : fields) {
        fieldName = field.getName();
        if(fieldName.endsWith(CD_TAG)){
          typ = StringUtils.removeEndStr(fieldName, CD_TAG);
          field.setAccessible(true);
          setDscp(obj, typ, getDscp(dictCache, typ, field.get(obj).toString()));
        }
      }
    }
  }
  
  /** 
   *  @Description	: 根据字典更新某个集合的描述内容
   *  @return         : void
   *  @Creation Date  : 2016年5月23日 上午1:02:31 
   *  @Author         : chichangchao
   */
  public static void updateDscp(Map<String, List<?>> dictCache, List<?> objs) 
      throws IllegalArgumentException, IllegalAccessException {
    if(CollectionUtils.isEmpty(objs)) return;
    for (Object obj : objs) {
      updateDscp(dictCache, obj);
    }
  }
  
  /** 
   *  @Description	: 根据代码值获取指定字典得描述内容
   *  @return         : String
   *  @Creation Date  : 2016年5月23日 上午12:19:53 
   *  @Author         : chichangchao
   */
  private static String getDscp(Map<String, List<?>> dictCache, String typ, String typValue) 
      throws IllegalArgumentException, IllegalAccessException {
    // 获取对应字典
    // TODO Maint增加Redis后，修改此位置，去除参数dictCache即可
    List<?> dicts = dictCache.get(typ);
    if(dicts == null) return null;
    // 代码域
    Field cdField = null;
    // 描述内容
    String dscp = null;
    // 根据代码值获取指定字典得描述内容
    for (Object dict : dicts) {
      // 获取代码域
      cdField = ReflectUtils.getField(dict, CD_TAG.toLowerCase());
      // 判断代码域的值是否与传入的代码值相同
      // 相同则获取其所对应的描述并跳出循环，否则继续循环
      if(cdField != null && Objects.equals(cdField.get(dict), typValue)){
        Field dscpField = ReflectUtils.getField(dict, DSCP_TAG.toLowerCase());
        if(dscpField != null)
          dscp = dscpField.get(dict).toString();
        return dscp;
      }
    }
    return dscp;
  }
  
  /** 
   *  @Description	: 根据字典类型设置某个对象的对应的字典描述
   *  @return         : void
   *  @Creation Date  : 2016年5月22日 下午11:54:28 
   *  @Author         : chichangchao
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  private static void setDscp(Object obj, String typ, String dscp) 
      throws IllegalArgumentException, IllegalAccessException{
    // 如果描述存在，则设置描述
    if(dscp == null) return;
    if(obj instanceof Map){
      Set<Entry<String, Object>> set = ((Map) obj).entrySet();
      for (Entry<String, Object> entry : set) {
        String key = entry.getKey();
        if(key.startsWith(typ) && key.endsWith(CD_DSCP_TAG)){
          entry.setValue(dscp);
          break;
        }
      }
    }else{
      Field[] fields = ReflectUtils.getFields(obj);
      String fieldName = null;
      for (Field field : fields) {
        fieldName = field.getName();
        if(fieldName.startsWith(typ) && fieldName.endsWith(CD_DSCP_TAG)){
          field.setAccessible(true);
          field.set(obj, dscp);
          break;
        }
      }
    }
  }
}
